﻿////////////////////////////////////////////////
/// Провайдер форматирования TeX
/// обеспечивает преобразование разметки на языке TeX в gif-картинку
/// при помощи внешнего сервиса
/// Работает с тэгом <math>
/// Василий Кудрявцев
/// 22 декабря 2008 года

using System;
using System.IO;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Security.Cryptography;
using ScrewTurn.Wiki.PluginFramework;

namespace ScrewTurn.Wiki.PluginPack
{
    class TeXMarkupFormatter : IFormatterProvider
    {
        private static Regex math = new Regex(@"\<math\>(.|\n|\r)*?\<\/math\>", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
        private string uploadDirPath = string.Empty;

        #region IFormatterProvider Members

        bool IFormatterProvider.PerformPhase1
        {
            get { return true; }
        }

        bool IFormatterProvider.PerformPhase2
        {
            get { return false; }
        }

        bool IFormatterProvider.PerformPhase3
        {
            get { return false; }
        }

        string IFormatterProvider.Format(string raw, ContextInformation context, FormattingPhase phase)
        {
            // Process only real pages, not system fragments like sidebar
            if (phase == FormattingPhase.Phase1 && context.Page != null)
            {
                var match = math.Match(raw);
                while (match.Success)
                {
                    raw = raw.Remove(match.Index, match.Length);
                    var formula = match.Value.Substring(6, match.Length - 13);
                    var filename = "TeXImageCache\\" + ComputeHash(formula) + ".gif";
                    if (!File.Exists(String.Format("{0}{1}", uploadDirPath, filename)))
                    {

                        try
                        {
                            var client = new WebClient();
                            using (var responseStream = client.OpenRead(String.Format("http://www.forkosh.dreamhost.com/mimetex.cgi?{0}", formula)))
                            using (var str = new StreamReader(responseStream, Encoding.GetEncoding(866)))
                            using (var wrt = new StreamWriter(
                                        new FileStream(String.Format("{0}{1}", uploadDirPath, filename), FileMode.Create),
                                        Encoding.GetEncoding(866)))
                            {

                                wrt.Write(str.ReadToEnd());
                                wrt.Flush();
                            }

                        }
                        catch (WebException)
                        {
                            raw = raw.Insert(match.Index, "Ошибка сервиса преобразования.");
                        }
                        catch (Exception ex)
                        {
                            raw = raw.Insert(match.Index, "Ошибка преобразования. Возможно неверное выражение");
                        }
                    }



                    raw = raw.Insert(match.Index, "[image||{UP}{0}|]".Replace("{0}", filename));
                    match = math.Match(raw);
                }

                return raw;
            }
            else
            {
                return raw;
            }
        }

        #endregion

        #region IProvider Members

        void IProvider.Init(IHost host, string config)
        {
            uploadDirPath = host.GetSettingValue(SettingName.UploadDirectory);
        }

        void IProvider.Shutdown()
        {

        }

        ComponentInformation IProvider.Information
        {
            get { return new ComponentInformation("TeX Markup Provider", "Vasiliy Kudriavtsev", "mailto:vklava@yandex.ru"); }
        }

        #endregion

        private static string ComputeHash(string plainText)
        {
            // Convert plain text into a byte array.
            byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);

            HashAlgorithm hash =  new MD5CryptoServiceProvider();

            // Compute hash value of our plain text.
            byte[] hashBytes = hash.ComputeHash(plainTextBytes);

            // Convert result into a base64-encoded string.
            string hashValue = String.Empty;
            foreach(byte b in hashBytes)
            {
                hashValue += b.ToString();
            }

            // Return the result.
            return hashValue;
        }



    }
}
